package inits

import (
	"animal_srv/basic/appConfig"
	"fmt"
	"github.com/elastic/go-elasticsearch/v7"
	"github.com/fsnotify/fsnotify"
	"github.com/hashicorp/consul/api"
	"github.com/redis/go-redis/v9"
	"github.com/spf13/viper"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"log"
	"time"
)

func init() {
	ConfigInit()
	MysqlInit()
	RedisInit()

	err := ConsulInit()
	if err != nil {
		log.Fatalf("Consul 初始化失败: %v", err)
	}
}

func ConfigInit() {
	viper.SetConfigFile("D:\\gowork\\src\\zk\\zg5_zk3\\animal_srv\\config.yaml")
	viper.ReadInConfig()
	viper.Unmarshal(&appConfig.ConfigData)
	fmt.Println(appConfig.ConfigData)

	viper.WatchConfig()
	viper.OnConfigChange(func(e fsnotify.Event) {
		err := viper.Unmarshal(&appConfig.ConfigData)
		if err != nil {
			return
		}
		fmt.Println("配置文件跟新成功", appConfig.ConfigData)
	})
}

func MysqlInit() {
	data := appConfig.ConfigData.Mysql
	var err error

	appConfig.Once.Do(func() {
		dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
			data.User, data.Passwd, data.Host, data.Port, data.Database)

		appConfig.DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
		if err != nil {
			panic(fmt.Sprintf("无法连接数据库: %v", err))
		} else {
			log.Println("Mysql数据库连接成功")
		}

		sqlDB, err := appConfig.DB.DB()
		// SetMaxIdleConns 设置空闲连接池中连接的最大数量。
		sqlDB.SetMaxIdleConns(10)
		// SetMaxOpenConns 设置打开数据库连接的最大数量。
		sqlDB.SetMaxOpenConns(100)
		// SetConnMaxLifetime 设置了可以重新使用连接的最大时间。
		sqlDB.SetConnMaxLifetime(time.Hour)

		err = appConfig.DB.AutoMigrate()
		if err != nil {
			panic("数据库迁移失败")
		} else {
			log.Println("数据库迁移成功")
		}
	})
}

func RedisInit() {
	data := appConfig.ConfigData.Redis
	appConfig.Rdb = redis.NewClient(&redis.Options{
		Addr:     data.Addr,
		Password: data.Passwd, // no password set
		DB:       0,           // use default DB
	})

	err := appConfig.Rdb.Set(appConfig.Ctx, "key", "value", 0).Err()
	if err != nil {
		panic(err)
	}

	log.Println("redis数据库连接成功")
}

func EsInit() {
	var err error
	cfg := elasticsearch.Config{
		Addresses: []string{
			"http://14.103.156.92:9200",
		},
	}
	appConfig.EsClient, err = elasticsearch.NewClient(cfg)

	_, err = appConfig.EsClient.Info()
	if err != nil {
		panic(err)
	}
	log.Println("Es连接成功")
}

// ConsulInit 初始化 Consul 客户端
func ConsulInit() error {
	// 从配置文件读取 Consul 地址（推荐，避免硬编码）
	consulAddr := appConfig.ConfigData.Consul.Addr // 需在 config.yaml 中配置
	if consulAddr == "" {
		consulAddr = "127.0.0.1:8500" // 默认地址
	}

	// 创建 Consul 配置
	config := api.DefaultConfig()
	config.Address = consulAddr

	// 初始化客户端并存储到全局变量
	client, err := api.NewClient(config)
	if err != nil {
		return fmt.Errorf("Consul 客户端初始化失败: %v", err)
	}
	appConfig.ConsulClient = client // 需在 global.go 中定义 ConsulClient 变量
	return nil
}

// RegisterToConsul 注册 gRPC 服务到 Consul
func RegisterToConsul(serviceName, ip string, port int) error {
	if appConfig.ConsulClient == nil {
		return fmt.Errorf("Consul 客户端未初始化")
	}

	// 服务注册信息
	registration := &api.AgentServiceRegistration{
		Name:    serviceName,                                    // 服务名（如 "user-srv"）
		ID:      fmt.Sprintf("%s-%s:%d", serviceName, ip, port), // 唯一ID
		Address: ip,                                             // gRPC 服务IP
		Port:    port,                                           // gRPC 服务端口
		Check: &api.AgentServiceCheck{ // 健康检查（gRPC 推荐用 TCP 检查）
			TCPSocket:                      fmt.Sprintf("%s:%d", ip, port),
			Interval:                       "5s",  // 检查间隔
			Timeout:                        "2s",  // 超时时间
			DeregisterCriticalServiceAfter: "30s", // 不健康后自动注销
		},
	}
	// 注册服务
	return appConfig.ConsulClient.Agent().ServiceRegister(registration)

}

// DeregisterFromConsul 从 Consul 注销服务
func DeregisterFromConsul(serviceID string) error {
	if appConfig.ConsulClient == nil {
		return nil
	}
	return appConfig.ConsulClient.Agent().ServiceDeregister(serviceID)
}
